package com.dingreading.cloud.admin.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.admin.dto.StoreDto;
import com.dingreading.cloud.admin.entity.*;
import com.dingreading.cloud.admin.mapper.StoresMapper;
import com.dingreading.cloud.admin.service.*;
import com.dingreading.cloud.admin.util.StoreFollowEnum;
import com.dingreading.cloud.admin.util.StoreFollowUtil;
import com.dingreading.cloud.admin.util.redis.RedisService;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RefreshScope
@RestController
@RequestMapping("/system/stores")
@Api(tags = "总部-门店信息管理")
public class StoresController {

    @Resource
    private CorporationsService corporationsService;
    @Resource
    private StoresService storesService;
    @Resource
    private StaffRolesService staffRolesService;
    @Resource
    private StoreProtectService storeProtectService;
    @Resource
    private StaffService staffService;
    @Resource
    private StoresMapper storesMapper;
    @Resource
    private RedisService redisService;


    @ApiOperation(value = "分页列表")
    @PostMapping(value = "/pageList")
    public R<Object> pageList(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid", required = false) String corpUid,
            @ApiParam(value = "门店名/手机号/地址/运营人员姓名") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "是否有运营人员 1.有 0.没有") @RequestParam(value = "operateStatus", required = false) Integer operateStatus,
            @ApiParam(value = "启用状态") @RequestParam(value = "enabled", required = false) Integer enabled,
            @ApiParam(value = "是否启动 1.已启动 0.未启动") @RequestParam(value = "activated", required = false) Integer activated,
            @ApiParam(value = "角色类型 1.运营督导 2.运营人员") @RequestParam(value = "roleType", required = false) Integer roleType,
            @ApiParam(value = "是否上传合同 1.是 0.否") @RequestParam(value = "contractStatus", required = false) Integer contractStatus,
            @ApiParam(value = "是否有保护范围 1.是 0.否") @RequestParam(value = "protectStatus", required = false) Integer protectStatus
    ) {
        PageDto<StoreDto> dto = storesService.pageList(
                pageUtil, corpUid, keyword, operateStatus, enabled, roleType, headStaffUid, activated, contractStatus,
                protectStatus
        );
        return R.ok(dto);
    }


    @ApiOperation(value = "搜索门店信息")
    @PostMapping(value = "/searchStore")
    public R<Object> pageList(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店名/手机号/地址/运营人员姓名") @RequestParam(value = "keyword") String keyword
    ) {
        return storesService.searchStore(headStaffUid, headStaffName, keyword);
    }


    @ApiOperation(value = "获取门店信息")
    @PostMapping(value = "/getBean", produces = "application/json; charset=UTF-8")
    public R<Object> getBean(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid
    ) {
        StoreDto data = storesService.getDtoByUid(storeUid);
        if (null == data)
            return R.failGet();

        return R.ok(data);
    }


    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "编辑门店信息")
    @PostMapping(value = "/editBean", produces = "application/json; charset=UTF-8")
    public R<Object> editBean(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "合同编号") @RequestParam(value = "contractCode", required = false) String contractCode,
            @ApiParam(value = "签约日期") @RequestParam(value = "signDate", required = false) String signDate,
            @ApiParam(value = "详细地址") @RequestParam(value = "address", required = false) String address,
            @ApiParam(value = "联系方式") @RequestParam(value = "phone", required = false) String phone,
            @ApiParam(value = "省") @RequestParam(value = "province", required = false) String province,
            @ApiParam(value = "市") @RequestParam(value = "city", required = false) String city,
            @ApiParam(value = "区县") @RequestParam(value = "county", required = false) String county,
            @ApiParam(value = "合作类型") @RequestParam(value = "cooperationType") String cooperationType,
            @ApiParam(value = "运营类型") @RequestParam(value = "operationType") Integer operationType,
            @ApiParam(value = "科目类型（运营类型是轻量产品加盟时必填）") @RequestParam(value = "subjectType", required = false) String subjectType,
            @ApiParam(value = "服务类型（运营类型是轻量产品加盟时必填）") @RequestParam(value = "projectType", required = false) String projectType,
            @ApiParam(value = "叮叮学院类型") @RequestParam(value = "courseType", required = false) String courseType
    ) throws Exception {
        if (StringUtils.isNotBlank(phone) && phone.length() != 11)
            return R.fail("联系方式错误");

        if (operationType != null && operationType.equals(EnumOperationType.EASY_PRODUCT_JOIN.getType())
                && (StringUtils.isBlank(subjectType) || StringUtils.isBlank(projectType)))
            return R.fail("运营类型是轻量产品加盟时，需要选择科目和服务");

        Stores data = storesService.getByUid(storeUid);
        if (null == data) return R.fail("门店不存在");

        data.setStoreName(storeName);
        data.setAddress(address);
        data.setPhone(phone);
        data.setCooperationType(cooperationType);
        data.setOperationType(operationType);
        data.setSubjectType(StringUtils.isNotBlank(subjectType) ? StringUtils.deleteWhitespace(subjectType) : "");
        data.setProjectType(StringUtils.isNotBlank(projectType) ? StringUtils.deleteWhitespace(projectType) : "");
        data.setCourseType(StringUtils.isNotBlank(courseType) ? StringUtils.deleteWhitespace(courseType) : "");
        data.setProvince(StringUtils.isNotBlank(province) ? province : "");
        data.setCity(StringUtils.isNotBlank(city) ? city : "");
        data.setCounty(StringUtils.isNotBlank(county) ? county : "");
        data.setContractCode(contractCode);
        if (StringUtils.isNotBlank(signDate)) {
            data.setSignDate(DateUtil.parseDate(signDate));
        } else {
            data.setSignDate(null);
        }
        storesMapper.insertOrUpdate(data, false);

        clearRedis();
        return R.ok();
    }

    @ApiOperation(value = "设置门店启动")
    @PostMapping(value = "/updateActivated")
    public R<Object> updateActivated(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "启动状态 0.禁用 1.启用") @RequestParam(value = "activated") Integer activated
    ) {
        Stores data = storesService.getByUid(storeUid);
        if (null == data)
            return R.fail("门店不存在");
        if (data.getActivated().equals(1)) {
            if (TimeUtil.moreThanDay(data.getActivatedTime(), 30))
                return R.fail("启动超过30天，不能操作");
        }

        boolean b = storesService.updateActivated(storeUid, activated);
        if (!b)
            return R.fail("操作失败");

        // 跟进记录
        String followUid = activated.equals(1) ? StoreFollowEnum.STORE_ACTIVATE_ON.getType() : StoreFollowEnum.STORE_ACTIVATE_OFF.getType();
        StoreFollowUtil.newSystemLog(
                followUid, "", data.getCorpUid(), data.getUid(), headStaffUid, headStaffName
        );
        return R.ok();
    }

    @ApiOperation(value = "设置门店启动")
    @PostMapping(value = "/updateEnabled")
    public R<Object> updateEnabled(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "启用状态 0.禁用 1.启用") @RequestParam(value = "enabled") Integer enabled
    ) {
        Stores data = storesService.getByUid(storeUid);
        if (null == data)
            return R.fail("门店不存在");

        boolean b = storesService.updateEnabled(storeUid, enabled);
        if (!b)
            return R.fail("操作失败");

        // 启用/禁用员工
        b = staffService.updateEnabledByStoreUid(storeUid, enabled);
        if (b) {
            // 启用/禁用员工角色
            staffRolesService.updateEnabledByStoreUid(headStaffUid, headStaffName, storeUid, enabled);
        }
        // 启用/禁用区域范围的经纬度数据
        if (data.getProtectType() != null && data.getProtectType().equals(2)) {
            storeProtectService.updateEnabled(storeUid, enabled);
        }

        // 跟进记录
        String followUid = enabled.equals(1) ? StoreFollowEnum.STORE_ENABLED_ON.getType() : StoreFollowEnum.STORE_ENABLED_OFF.getType();
        StoreFollowUtil.newSystemLog(
                followUid, "", data.getCorpUid(), data.getUid(), headStaffUid, headStaffName
        );

        return R.ok();
    }

    @ApiOperation(value = "获取所有门店")
    @PostMapping(value = "/getAll")
    public R<Object> getAll(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店名/详细地址") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "启用状态") @RequestParam(value = "enabled", required = false) Integer enabled
    ) {
        List<Stores> list = storesService.getByKeywordAndEnable(keyword, enabled);
        return R.ok(list);
    }


    @ApiOperation(value = "获取公司的所有门店")
    @PostMapping(value = "/getCorpStores")
    public R<Object> getCorpStores(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid", required = false) String corpUid,
            @ApiParam(value = "启用状态") @RequestParam(value = "enabled", required = false) Integer enabled
    ) {
        List<Stores> list = storesService.getByCorpUid(corpUid, enabled);
        return R.ok(list);
    }


    @ApiOperation(value = "获取所有门店及经纬度")
    @PostMapping(value = "/getStoreMarker", produces = "application/json; charset=UTF-8")
    public R<Object> getStoreMarker(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName
    ) {
        List<Stores> list = storesService.getStoreMarker();
        return R.ok(list);
    }

    @ApiOperation(value = "设置运营人员")
    @PostMapping(value = "/setOperateStaff", produces = "application/json; charset=UTF-8")
    public R<Object> setOperateStaff(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "运营人员uid") @RequestParam(value = "operateStaffUid") String operateStaffUid,
            @ApiParam(value = "运营人员姓名") @RequestParam(value = "operateStaffName") String operateStaffName,
            @ApiParam(value = "运营人员手机号") @RequestParam(value = "operateStaffPhone") String operateStaffPhone
    ) {
        Stores data = storesService.getByUid(storeUid);
        if (null == data)
            return R.fail("门店不存在");

        boolean l = storesService.updateOperateInfo(storeUid, operateStaffUid, operateStaffName, operateStaffPhone);
        if (!l)
            return R.fail("设置运营人员失败");

        return R.ok();
    }


    @ApiOperation(value = "获取自营的门店（财务）")
    @PostMapping(value = "/getSelfStoreList")
    public R<Object> getSelfStoreList(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名称") @RequestParam(value = "headStaffName") String headStaffName
    ) {
        List<Stores> list = storesService.selfAndConsortiumList();
        return R.ok(list);
    }


    @ApiOperation(value = "更新门店的保护范围")
    @PostMapping(value = "/updateProtect")
    public R<Object> updateProtect(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "保护类型 circle.圆形、polygon.多边形") @RequestParam(value = "protectType") Integer protectType,
            @ApiParam(value = "中心经度") @RequestParam(value = "lng") String lng,
            @ApiParam(value = "中心纬度") @RequestParam(value = "lat") String lat,
            @ApiParam(value = "保护半径/米") @RequestParam(value = "protectRadius", required = false) Integer protectRadius,
            @ApiParam(value = "区域经纬度集合[{lng:'',lat:''}]") @RequestBody(required = false) List<StoreProtect> lngLatJson
    ) {
        if (protectType.equals(1)) {
            if (protectRadius == null || protectRadius <= 0)
                return R.fail("请填写保护半径");
        } else if (protectType.equals(2)) {
            if (CollectionUtils.isEmpty(lngLatJson))
                return R.fail("区域经纬度不能为空");
        } else {
            return R.fail("保护类型错误");
        }

        Stores stores = storesService.getByUid(storeUid);
        if (null == stores)
            return R.fail("未查询到门店");

        List<StoreProtect> newList = new ArrayList<>();
        if (protectType.equals(2) && CollectionUtils.isNotEmpty(lngLatJson)) {
            for (int i = 0; i < lngLatJson.size(); i++) {
                StoreProtect object = lngLatJson.get(i);
                String lngStr = object.getLng();
                String latStr = object.getLat();
                if (StringUtils.isBlank(lngStr) || StringUtils.isBlank(latStr))
                    return R.fail("区域经纬度数据错误");

                StoreProtect data = new StoreProtect();
                data.setCorpUid(stores.getCorpUid());
                data.setStoreUid(storeUid);
                data.setLng(lngStr);
                data.setLat(latStr);
                data.setEnabled(1);
                data.setAddStaffUid(headStaffUid);
                data.setAddStaffName(headStaffName);
                newList.add(data);
            }
        }

        // 更新门店的经纬度信息
        boolean l = storesService.updateLngAndLat(storeUid, lng, lat, protectType, protectRadius);
        if (!l)
            return R.fail("门店更新经纬度失败");

        // 删除原保护区域经纬度
        storeProtectService.deleteByStoreUid(storeUid);
        // 保存区域经纬度
        if (CollectionUtils.isNotEmpty(newList))
            storeProtectService.saveOrUpdateBatch(newList);

        // 跟进记录
        String content = protectType.equals(1) ? "圆形保护范围，半径：" + protectRadius + "米" : "区域保护范围";
        StoreFollowUtil.newSystemLog(
                StoreFollowEnum.STORE_PROTECT.getType(), content,
                stores.getCorpUid(), storeUid, headStaffUid, headStaffName
        );
        return R.ok();
    }

    @ApiOperation(value = "获取门店的保护范围")
    @PostMapping(value = "/getProtectInfo", produces = "application/json; charset=UTF-8")
    public R<Object> getProtectInfo(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid
    ) {
        Stores data = storesService.getByUid(storeUid);
        if (null == data) return R.fail("合同获取失败");

        Integer protectType = data.getProtectType();
        if (protectType == null) {
            return R.ok();
        } else if (protectType.equals(1)) {
            JSONObject object = new JSONObject();
            object.put("storeName", data.getStoreName());
            object.put("storeUid", data.getUid());
            object.put("enabled", data.getEnabled());
            object.put("lng", data.getLng());
            object.put("lat", data.getLat());
            object.put("protectType", data.getProtectType());
            object.put("protectRange", NepUtil.nullToZero(data.getProtectRadius()));
            return R.ok(object);
        } else if (protectType.equals(2)) {
            List<StoreProtect> protects = storeProtectService.getByStoreUid(storeUid);
            JSONArray lngLatObj = new JSONArray();
            if (CollectionUtils.isNotEmpty(protects)) {
                for (StoreProtect protect : protects) {
                    JSONObject object = new JSONObject();
                    object.put("lng", protect.getLng());
                    object.put("lat", protect.getLat());
                    lngLatObj.add(object);
                }
            }

            JSONObject object = new JSONObject();
            object.put("storeName", data.getStoreName());
            object.put("storeUid", data.getUid());
            object.put("enabled", data.getEnabled());
            object.put("lng", data.getLng());
            object.put("lat", data.getLat());
            object.put("protectType", data.getProtectType());
            object.put("list", lngLatObj);
            return R.ok(object);
        }

        return R.ok();
    }

    @ApiOperation(value = "获取50公里内其他门店的保护范围")
    @PostMapping(value = "/getNearProtects", produces = "application/json; charset=UTF-8")
    public R<Object> getNearProtects(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "经度") @RequestParam(value = "lng") String lng,
            @ApiParam(value = "纬度") @RequestParam(value = "lat") String lat
    ) {
        if (StringUtils.isBlank(lng) || StringUtils.isBlank(lat))
            return R.fail("经度或者纬度不能为空");

        // 获取5公里范围内的除本门店的附近门店
        double kilometers = 50d;
        Map<String, Double> map = TencentMapUtil.getFourPoint(lng, lat, kilometers);
        String latitudeMin = map.get("latitudeMin").toString();
        String latitudeMax = map.get("latitudeMax").toString();
        String longitudeMin = map.get("longitudeMin").toString();
        String longitudeMax = map.get("longitudeMax").toString();

        JSONObject jsonObject = new JSONObject();
        // 获取附近圆形保护范围的门店
        List<Stores> cycleStoreList = storesService.getNearCycleStoreList(longitudeMin, longitudeMax, latitudeMin, latitudeMax);
        if (CollectionUtils.isNotEmpty(cycleStoreList)) {
            JSONArray circleList = new JSONArray();
            if (CollectionUtils.isNotEmpty(cycleStoreList)) {
                for (Stores data : cycleStoreList) {
                    JSONObject object = new JSONObject();
                    object.put("storeName", data.getStoreName());
                    object.put("storeUid", data.getUid());
                    object.put("enabled", data.getEnabled());
                    object.put("lng", data.getLng());
                    object.put("lat", data.getLat());
                    object.put("protectType", data.getProtectType());
                    object.put("protectRange", NepUtil.nullToZero(data.getProtectRadius()));
                    circleList.add(object);
                }
            }
            jsonObject.put("circleList", circleList);
        }

        // 获取附近区域保护范围的门店
        List<String> storeUids = storeProtectService.getPolygonStoreList(longitudeMin, longitudeMax, latitudeMin, latitudeMax);
        if (CollectionUtils.isNotEmpty(storeUids)) {
            JSONArray polygonList = new JSONArray();

            List<Stores> polygons = storesService.getByUids(storeUids);
            if (CollectionUtils.isNotEmpty(polygons)) {
                // 获取区域保护的门店的经纬度
                List<StoreProtect> protectList = storeProtectService.listByStoreUid(storeUids);
                Map<String, List<StoreProtect>> maps = new HashMap<>();
                if (CollectionUtils.isNotEmpty(protectList))
                    maps = protectList.stream().collect(Collectors.groupingBy(StoreProtect::getStoreUid));

                for (Stores data : polygons) {
                    List<StoreProtect> protects = maps.get(data.getUid());
                    List<JSONObject> lngLatList = new ArrayList<>();
                    if (CollectionUtils.isNotEmpty(protects)) {
                        for (StoreProtect protect : protects) {
                            JSONObject object = new JSONObject();
                            object.put("lng", protect.getLng());
                            object.put("lat", protect.getLat());
                            lngLatList.add(object);
                        }
                    }

                    JSONObject object = new JSONObject();
                    object.put("storeName", data.getStoreName());
                    object.put("storeUid", data.getUid());
                    object.put("enabled", data.getEnabled());
                    object.put("lng", data.getLng());
                    object.put("lat", data.getLat());
                    object.put("protectType", data.getProtectType());
                    object.put("list", lngLatList);
                    polygonList.add(object);
                }
            }
            jsonObject.put("polygonList", polygonList);
        }

        return R.ok(jsonObject);
    }


    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "新增门店并批量创建员工及角色")
    @PostMapping(value = "/newStoreAndStaffs", produces = "application/json; charset=UTF-8")
    public R<Object> newStoreAndStaffs(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店名") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "门店联系人电话") @RequestParam(value = "phone", required = false) String phone,
            @ApiParam(value = "门店地址") @RequestParam(value = "address", required = false) String address,
            @ApiParam(value = "省") @RequestParam(value = "province", required = false) String province,
            @ApiParam(value = "市") @RequestParam(value = "city", required = false) String city,
            @ApiParam(value = "区县") @RequestParam(value = "county", required = false) String county,
            @ApiParam(value = "合同编号") @RequestParam(value = "contractCode", required = false) String contractCode,
            @ApiParam(value = "签约日期") @RequestParam(value = "signDate", required = false) String signDate,
            @ApiParam(value = "合作类型") @RequestParam(value = "cooperationType", required = false) String cooperationType,
            @ApiParam(value = "运营类型") @RequestParam(value = "operationType", required = false) Integer operationType,
            @ApiParam(value = "科目类型（运营类型是轻量产品加盟时必填）") @RequestParam(value = "subjectType", required = false) String subjectType,
            @ApiParam(value = "服务类型（运营类型是轻量产品加盟时必填）") @RequestParam(value = "projectType", required = false) String projectType,
            @ApiParam(value = "导读数量") @RequestParam(value = "daoduNum", required = false) Integer daoduNum,
            @ApiParam(value = "组长数量") @RequestParam(value = "zuzhangNum", required = false) Integer zuzhangNum,
            @ApiParam(value = "顾问数量") @RequestParam(value = "guwenNum", required = false) Integer guwenNum,
            @ApiParam(value = "店长数量") @RequestParam(value = "dianzhangNum", required = false) Integer dianzhangNum
    ) throws Exception {
        Corporations corporations = corporationsService.getByUid(corpUid);
        if (corporations == null)
            return R.fail("公司获取失败");

        if (operationType != null && operationType.equals(EnumOperationType.EASY_PRODUCT_JOIN.getType())
                && (StringUtils.isBlank(subjectType) || StringUtils.isBlank(projectType)))
            return R.fail("运营类型是轻量产品加盟时，需要选择科目和服务");

        String storeUid = KitUtil.getUuid();

        // 创建门店
        Stores stores = new Stores();
        stores.setCorpUid(corpUid);
        stores.setUid(storeUid);
        stores.setStoreName(storeName);
        stores.setPhone(phone);
        stores.setAddress(address);
        stores.setCooperationType(cooperationType);
        stores.setOperationType(operationType);
        stores.setSubjectType(StringUtils.isNotBlank(subjectType) ? StringUtils.deleteWhitespace(subjectType) : "");
        stores.setProjectType(StringUtils.isNotBlank(projectType) ? StringUtils.deleteWhitespace(projectType) : "");
        stores.setProvince(province);
        stores.setCity(city);
        stores.setCounty(county);
        stores.setContractCode(contractCode);
        if (StringUtils.isNotBlank(signDate)) {
            stores.setSignDate(DateUtil.parseDate(signDate));
        } else {
            stores.setSignDate(null);
        }
        stores.setActivated(0);
        stores.setEnabled(1);
        storesMapper.insertOrUpdate(stores, false);

        // 获取公司下的最新username
        int usernameNum = getUsernameNum(corpUid);
        if (usernameNum <= 0)
            return R.fail("截取员工序号失败");

        // 跟进记录
        StoreFollowUtil.newSystemLog(
                StoreFollowEnum.STORE_CREATE.getType(), "门店名称：" + storeName,
                corpUid, storeUid, headStaffUid, headStaffName
        );

        // 批量创建员工与角色
        Map<String, List<String>> pwdMap = newStaffs(
                corpUid, storeUid, usernameNum, daoduNum, zuzhangNum, guwenNum, dianzhangNum, headStaffUid, headStaffName
        );
        return R.ok(pwdMap);
    }

    @Transactional(rollbackFor = Exception.class)
    @ApiOperation(value = "批量创建员工及角色")
    @PostMapping(value = "/newStaffs", produces = "application/json; charset=UTF-8")
    public R<Object> newStaffs(
            @ApiParam(value = "总部员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "总部员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "导读数量") @RequestParam(value = "daoduNum", required = false) Integer daoduNum,
            @ApiParam(value = "组长数量") @RequestParam(value = "zuzhangNum", required = false) Integer zuzhangNum,
            @ApiParam(value = "顾问数量") @RequestParam(value = "guwenNum", required = false) Integer guwenNum,
            @ApiParam(value = "店长数量") @RequestParam(value = "dianzhangNum", required = false) Integer dianzhangNum
    ) {
        Stores data = storesService.getByUid(storeUid);
        if (null == data)
            return R.fail("门店不存在");

        String corpUid = data.getCorpUid();
        // 获取公司下的最新username
        int usernameNum = getUsernameNum(corpUid);
        if (usernameNum <= 0)
            return R.fail("截取员工序号失败");

        // 批量创建员工与角色
        Map<String, List<String>> pwdMap = newStaffs(
                corpUid, storeUid, usernameNum, daoduNum, zuzhangNum, guwenNum, dianzhangNum, headStaffUid, headStaffName
        );
        return R.ok(pwdMap);
    }


    /**
     * 获取公司下的员工账号的序号
     */
    private int getUsernameNum(String corpUid) {
        int usernameNum = 1;
        Staff lastStaff = staffService.getLastUsername(corpUid);
        if (null != lastStaff) {
            String lastUsername = lastStaff.getUsername();
            // 在最后一次出现"yyMm"后获取其之后的字符串
            String lastString = StringUtils.substringAfterLast(lastUsername, corpUid);
            if (StringUtils.isBlank(lastString))
                return 0;
            int num = Integer.parseInt(lastString);
            usernameNum = num + 1;
            // 数字最后一位是4则跳过
            usernameNum = TextUtils.dealLastFour(usernameNum);
        }
        return usernameNum;
    }

    /**
     * 批量创建员工
     *
     * @param usernameNum  员工账号的序号
     * @param dianzhangNum 店长数量
     * @param guwenNum     顾问数量
     * @param zuzhangNum   组长数量
     * @param daoduNum     导读数量
     */
    private Map<String, List<String>> newStaffs(
            String corpUid, String storeUid, int usernameNum, Integer daoduNum, Integer zuzhangNum, Integer guwenNum, Integer dianzhangNum,
            String headStaffUid, String headStaffName
    ) {
        daoduNum = NepUtil.nullToZero(daoduNum);
        zuzhangNum = NepUtil.nullToZero(zuzhangNum);
        guwenNum = NepUtil.nullToZero(guwenNum);
        dianzhangNum = NepUtil.nullToZero(dianzhangNum);
        int totalNum = daoduNum + zuzhangNum + guwenNum + dianzhangNum;
        Map<String, List<String>> pwdMap = null;
        if (totalNum > 0) {
            pwdMap = new HashMap<>();
            int[] typeNum = {dianzhangNum, guwenNum, zuzhangNum, daoduNum};
            int uidNum = 0;
            // 获取员工uid
            List<String> staffUids = getUids(totalNum);
            List<Staff> staffList = new ArrayList<>();
            List<StaffRoles> staffRolesList = new ArrayList<>();
            for (int j = 0; j < typeNum.length; j++) {
                int num = typeNum[j];
                if (num <= 0) continue;
                EnumType.StaffRoleType roleType = null;
                if (j == 0) {
                    roleType = EnumType.StaffRoleType.DIANZHANG;
                } else if (j == 1) {
                    roleType = EnumType.StaffRoleType.GUWEN;
                } else if (j == 2) {
                    roleType = EnumType.StaffRoleType.ZUZHANG;
                } else {
                    roleType = EnumType.StaffRoleType.DAODU;
                }
                List<String> pwdList = new ArrayList<>();
                for (int i = 0; i < num; i++) {
                    String staffUid = staffUids.get(uidNum);
                    // 设置员工密码
                    String username = corpUid + usernameNum;
                    String pwdSalt = KitUtil.getRandomPwdStr(10);
                    String pwd = username + KitUtil.getRandomPwdStr(4);
                    String pwdSource = StaffPwdUtil.getPwdSource(pwd, pwdSalt);
                    String encodedPwd = MD5Util.MD5Encode(pwdSource);
                    pwdList.add("账号：" + username + " 密码：" + pwd);

                    Staff staff = newStaff(corpUid, staffUid, username, roleType.getAuth(), encodedPwd, pwdSalt, headStaffUid, headStaffName);
                    staffList.add(staff);

                    StaffRoles staffRoles = newStaffRole(staffUid, storeUid, roleType.getName(), roleType.getRoles(), headStaffUid, headStaffName);
                    staffRolesList.add(staffRoles);

                    usernameNum += 1;
                    // 数字最后一位是4则跳过
                    usernameNum = TextUtils.dealLastFour(usernameNum);
                    uidNum += 1;
                }
                pwdMap.put(roleType.getName(), pwdList);
            }

            if (CollectionUtils.isNotEmpty(staffList))
                staffService.saveOrUpdateBatch(staffList);
            if (CollectionUtils.isNotEmpty(staffRolesList))
                staffRolesService.saveOrUpdateBatch(staffRolesList);

            StoreFollowUtil.newSystemLog(
                    StoreFollowEnum.STORE_STAFF_CREATE.getType(), "员工账号数量：" + totalNum,
                    corpUid, storeUid, headStaffUid, headStaffName
            );
        }
        return pwdMap;
    }

    /**
     * 获取指定数量的员工uid
     */
    private List<String> getUids(int num) {
        List<String> uids = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            String uuid = KitUtil.getUuid();
            uids.add(uuid);
        }
        return uids;
    }

    /**
     * 创建员工
     */
    private Staff newStaff(String corpUid, String staffUid, String username, String auth, String encodedPwd, String pwdSalt, String headStaffUid, String headStaffName) {
        Staff staff = new Staff();
        staff.setCorpUid(corpUid);
        staff.setUid(staffUid);
        staff.setUsername(username);
        staff.setAuthApps(auth);
        staff.setEncodedPwd(encodedPwd);
        staff.setPwdSalt(pwdSalt);
        staff.setEnabled(1);
        staff.setAddStaffUid(headStaffUid);
        staff.setAddStaffName(headStaffName);
        staff.setLastStaffUid(headStaffUid);
        staff.setLastStaffName(headStaffName);
        return staff;
    }

    /**
     * 创建员工角色
     */
    private StaffRoles newStaffRole(String staffUid, String storeUid, String roleName, String roles, String headStaffUid, String headStaffName) {
        StaffRoles staffRoles = new StaffRoles();
        staffRoles.setStoreUid(storeUid);
        staffRoles.setStaffUid(staffUid);
        staffRoles.setIsHeadquarterStaff(0);
        staffRoles.setIsStoreStaff(1);
        staffRoles.setInStoreService(1);
        staffRoles.setRoleName(roleName);
        staffRoles.setRoles(roles);
        staffRoles.setEnabled(1);
        staffRoles.setAddStaffUid(headStaffUid);
        staffRoles.setAddStaffName(headStaffName);
        staffRoles.setLastStaffUid(headStaffUid);
        staffRoles.setLastStaffName(headStaffName);
        return staffRoles;
    }

    /**
     * 清空redis缓存
     */
    private void clearRedis() {
        redisService.setNullLike(RedisParam.MAIN_SUBJECT);
        redisService.setNullLike(RedisParam.CHILD_SUBJECT);
        redisService.setNullLike(RedisParam.DXH_SUBJECT);
        redisService.setNullLike(RedisParam.HBJD_SUBJECT);
        redisService.setNullLike(RedisParam.HSYD_SUBJECT);

        redisService.setNullLike(RedisParam.PROJECT_CYCLE);
    }

}